package com.yequan.springmvc.handlermapping;

import java.lang.reflect.Method;
import java.util.HashMap;
import java.util.Map;

import javax.servlet.http.HttpServletRequest;


import com.yequan.springframework.beandefinition.BeanDefinition;
import com.yequan.springframework.factory.BeanFactory;
import com.yequan.springframework.factory.BeanFactoryAware;
import com.yequan.springframework.factory.DefaultListableBeanFactory;
import com.yequan.springmvc.annotation.Controller;
import com.yequan.springmvc.annotation.RequestMapping;
import com.yequan.springmvc.handlermapping.iface.HandlerMapping;

/**
 * 该处理器映射器，主要是通过bean标签的name值来存储url，和bean标签的class对应的处理器类建立映射
 * 
 * @author 灭霸詹
 *
 */
public class RequestMappingHandlerMapping implements HandlerMapping, BeanFactoryAware {

	private DefaultListableBeanFactory beanFactory;
	/**
	 * 存储url和处理器的映射关系
	 */
	private Map<String, HandlerMethod> urlHandlerMethodMap = new HashMap<>();

	/**
	 * 初始化方法
	 */
	public void init() {
		// 完成url和处理器的映射关系的建立
		// 获取bean容器，从bean容器中获取BeanDefinition集合
		try {
			Map<String, BeanDefinition> beanDefinitions = beanFactory.getBeanDefinitions();
			for (BeanDefinition beanDefinition : beanDefinitions.values()) {
				String beanClassName = beanDefinition.getBeanClassName();
				Class<?> clazz = Class.forName(beanClassName);
				// 判断该类型是否带有Controller或者RequestMapping注解
				if (isHandler(clazz)) {
					Method[] methods = clazz.getDeclaredMethods();
					for (Method method : methods) {
						if (method.isAnnotationPresent(RequestMapping.class)) {
							RequestMapping requestMapping = method.getAnnotation(RequestMapping.class);
							// 获取RequestMapping注解中的url值
							String url = requestMapping.value();

							// 获取Controller对象
							Object handler = beanFactory.getBean(beanDefinition.getBeanName());
							// 将Controller对象和Method封装到HandlerMethod对象中
							HandlerMethod handlerMethod = new HandlerMethod(handler, method);
							urlHandlerMethodMap.put(url, handlerMethod);
						}
					}
				}
			}
		} catch (Exception e) {
		}
	}

	private boolean isHandler(Class<?> clazz) {
		return (clazz.isAnnotationPresent(Controller.class) || clazz.isAnnotationPresent(RequestMapping.class));
	}

	@Override
	public Object getHandler(HttpServletRequest request) {
		String url = request.getRequestURI();
		return urlHandlerMethodMap.get(url);
	}

	@Override
	public void setBeanFacoty(BeanFactory beanFactory) {
		this.beanFactory = (DefaultListableBeanFactory) beanFactory;
	}

}
